package com.bwie.sixth.house.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.bwie.sixth.house.config.PageUtil;
import com.bwie.sixth.house.vo.NewEsQuaryVo;
import com.bwie.sixth.house.vo.NewEsVo;
import com.guli.common.utils.PageUtils;
import com.guli.common.utils.Query;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;


import com.bwie.sixth.house.dao.NewHouseDao;
import com.bwie.sixth.house.entity.NewHouseEntity;
import com.bwie.sixth.house.service.NewHouseService;


@Service("newHouseService")
public class NewHouseServiceImpl extends ServiceImpl<NewHouseDao, NewHouseEntity> implements NewHouseService {

    @Autowired
    private RestHighLevelClient client;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<NewHouseEntity> page = this.page(
                new Query<NewHouseEntity>().getPage(params),
                new QueryWrapper<NewHouseEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public PageUtil NewEsList(NewEsQuaryVo newEsQuaryVo, int size, int page) throws IOException {
        SearchRequest searchRequest = new SearchRequest("new");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        if (newEsQuaryVo!=null){
            if (newEsQuaryVo.getMapId()!=null&&newEsQuaryVo.getMapId()!=0){
                BoolQueryBuilder mapId = boolQueryBuilder.must(QueryBuilders.matchQuery("mapId", newEsQuaryVo.getMapId()));
                searchSourceBuilder.query(mapId);
            }
            if (newEsQuaryVo.getNewFeat()!=null&&newEsQuaryVo.getNewFeat()!=0){
                BoolQueryBuilder newFeat = boolQueryBuilder.must(QueryBuilders.matchQuery("newFeat", newEsQuaryVo.getNewFeat()));
                searchSourceBuilder.query(newFeat);
            }
            if (newEsQuaryVo.getNewFinish()!=null&&newEsQuaryVo.getNewFinish()!=0){
                BoolQueryBuilder newFinish = boolQueryBuilder.must(QueryBuilders.matchQuery("newFinish", newEsQuaryVo.getNewFinish()));
                searchSourceBuilder.query(newFinish);
            }
            if (newEsQuaryVo.getNewRoom()!=null&&newEsQuaryVo.getNewRoom()!=0){
                BoolQueryBuilder newRoom = boolQueryBuilder.must(QueryBuilders.matchQuery("newRoom", newEsQuaryVo.getNewRoom()));
                searchSourceBuilder.query(newRoom);
            }
            if (newEsQuaryVo.getNewType()!=null&&newEsQuaryVo.getNewType()!=0){
                BoolQueryBuilder newType = boolQueryBuilder.must(QueryBuilders.matchQuery("newType", newEsQuaryVo.getNewType()));
                searchSourceBuilder.query(newType);
            }
            if (newEsQuaryVo.getNewStartPrice()!=null&&newEsQuaryVo.getNewEndPrice()!=null&&newEsQuaryVo.getNewStartPrice()!=0&&newEsQuaryVo.getNewEndPrice()!=0){
                BoolQueryBuilder newPrice = boolQueryBuilder.filter(QueryBuilders.rangeQuery("newPrice")
                        .from(newEsQuaryVo.getNewStartPrice()).to(newEsQuaryVo.getNewEndPrice()));
                searchSourceBuilder.query(newPrice);
            }
            if (newEsQuaryVo.getNewBigArea()!=null&&newEsQuaryVo.getNewSmallArea()!=null&&newEsQuaryVo.getNewBigArea()!=0&&newEsQuaryVo.getNewSmallArea()!=0){
                BoolQueryBuilder newArea = boolQueryBuilder.filter(QueryBuilders.rangeQuery("newArea")
                        .from(newEsQuaryVo.getNewSmallArea()).to(newEsQuaryVo.getNewBigArea()));
                searchSourceBuilder.query(newArea);
            }
            if (newEsQuaryVo.getNewIntro()!=null&&newEsQuaryVo.getNewIntro()!=""){
                WildcardQueryBuilder newIntro = QueryBuilders.wildcardQuery("newIntro","*"+ newEsQuaryVo.getNewIntro()+"*");
                HighlightBuilder highlightBuilder = new HighlightBuilder();
                highlightBuilder.field("newIntro");//高亮的字段
                highlightBuilder.requireFieldMatch(false);//是否多个字段都高亮
                highlightBuilder.preTags("<span style=\"color: red;\">");//前缀后缀
                highlightBuilder.postTags("</span>");
                searchSourceBuilder.highlighter(highlightBuilder);

                searchSourceBuilder.query(newIntro);
            }
        }
        searchSourceBuilder.size(size);
        searchSourceBuilder.from((page-1)*size);

        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        SearchHits hits = searchResponse.getHits();
        TotalHits totalHits = hits.getTotalHits();
// the total number of hits, must be interpreted in the context of totalHits.relation
        long numHits = totalHits.value;
// whether the number of hits is accurate (EQUAL_TO) or a lower bound of the total (GREATER_THAN_OR_EQUAL_TO)
        TotalHits.Relation relation = totalHits.relation;
        float maxScore = hits.getMaxScore();
        SearchHit[] searchHits = hits.getHits();

        ArrayList<NewEsVo> listVos = new ArrayList<>();
        for (SearchHit hit : searchHits) {
            // do something with the SearchHit
            String index = hit.getIndex();
            String id = hit.getId();
            float score = hit.getScore();
            String sourceAsString = hit.getSourceAsString();
            NewEsVo newEsVo = JSON.parseObject(sourceAsString, new TypeReference<NewEsVo>() {
            });
            newEsVo.setNewId(Integer.valueOf(id));

            //解析高亮的字段
            //获取高亮字段
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField newIntro = highlightFields.get("newIntro");

            Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果

            //将原来的字段替换为高亮字段即可
            if(newIntro!=null){
                Text[] fragments = newIntro.fragments();
                String newIntro1="";
                for (Text text : fragments) {
                    newIntro1+=text;
                }
                newEsVo.setNewIntro(newIntro1);
            }
            listVos.add(newEsVo);
        }
        return new PageUtil<NewEsVo>(page,numHits,listVos,size);
    }

}